package com.zb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.entity.*;
import com.zb.extend.WorkSlaConditionExtend;
import com.zb.extend.WorkSlaConditionRemindEmpExtend;
import com.zb.extend.WorkSlaExtend;
import com.zb.extend.WorkSlaModuleExtend;
import com.zb.mapper.ZjWorkSlaMapper;
import com.zb.result.PageUtil;
import com.zb.service.ZjWorkSlaConditionRemindEmpService;
import com.zb.service.ZjWorkSlaConditionService;
import com.zb.service.ZjWorkSlaModuleService;
import com.zb.service.ZjWorkSlaService;
import com.zb.vo.*;
import org.jacoco.agent.rt.internal_1f1cc91.core.internal.flow.IFrame;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 工单SLA表 服务实现类
 * </p>
 *
 * @author WEN
 * @since 2024-02-04
 */
@Service
public class ZjWorkSlaServiceImpl extends ServiceImpl<ZjWorkSlaMapper, ZjWorkSla> implements ZjWorkSlaService {
    @Resource
    private ZjWorkSlaMapper workSlaMapper;
    @Resource
    private ZjWorkSlaModuleService workSlaModuleService;
    @Resource
    private ZjWorkSlaConditionService workSlaConditionService;
    @Resource
    private ZjWorkSlaConditionRemindEmpService workSlaConditionRemindEmpService;

    // 新增或修改SLA
    @Override
    @Transactional
    public void save(Long custAccId, WorkSlaVo slaVo) {
        Assert.isNull(workSlaMapper.existByName(custAccId, slaVo.getId(), slaVo.getName()), "SLA名称已重复：" + slaVo.getName());
        ZjWorkSla workSla = new ZjWorkSla();
        BeanUtil.copyProperties(slaVo, workSla);
        workSla.setDisabled(slaVo.getStatus());
        workSla.setRemindMode(String.join(",", slaVo.getRemindMode()));
        if (null != workSla.getId()) {
            this.updateById(workSla);
        } else {
            workSla.setId(IdWorker.getId());
            workSla.setCustAccId(custAccId);
            this.save(workSla);
        }
        workSlaModuleService.save(custAccId, workSla.getId(), slaVo.getModuleIds());
        workSlaConditionService.save(custAccId, workSla.getId(), slaVo.getSlaConditionVos());
    }

    // 获取工单策略SLA列表
    @Override
    public Map<String, Object> getList(Long custAccId, SelectVo selectVo) {
        PageUtil.setPageLimit(selectVo);
        List<ZjWorkSla> workSlaList = workSlaMapper.getList(custAccId, selectVo);
        List<Long> workSlaIds = workSlaList.stream().map(ZjWorkSla::getId).toList();
        List<WorkSlaModuleExtend> slaModuleExtendList = workSlaModuleService.getByWorkSlaIds(workSlaIds);
        List<ZjWorkSlaCondition> slaConditions = workSlaConditionService.getByWorkSlaIds(workSlaIds);
        List<WorkSlaListVo> voList = workSlaList.stream().map(sla -> {
            WorkSlaListVo vo = new WorkSlaListVo();
            BeanUtil.copyProperties(sla, vo);
            vo.setStatus(sla.getDisabled());
            vo.setCreateTime(sla.getGmtCreate());
            vo.setUpdateTime(sla.getGmtUpdate());
            vo.setModules(slaModuleExtendList.stream().filter(f -> Objects.equals(f.getWorkSlaId(), sla.getId())).map(WorkSlaModuleExtend::getModule).distinct().toList());
            vo.setConditions(slaConditions.stream().filter(f -> Objects.equals(f.getWorkSlaId(), sla.getId())).map(ZjWorkSlaCondition::getType).map(type -> {
                return 1 == type? "未分配客服" : 2 == type? "未派单" : 3 == type? "服务商未接单" : 4 == type? "工程师未接单" : 5 == type? "工程师未拨打电话" :
                        6 == type? "工程师未预约" : "工程师未签到";
            }).toList());
            return vo;
        }).toList();
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), workSlaMapper.getListCount(custAccId, selectVo), voList);
    }

    // 根据工单策略SLA ID获取修改前的数据
    @Override
    public WorkSlaVo getBeforeEditData(Long id) {
        ZjWorkSla workSla = this.getById(id);
        Assert.notNull(workSla, "工单策略SLA参数[ "+ id +" ]的数据不存在");
        WorkSlaVo vo = new WorkSlaVo();
        BeanUtil.copyProperties(workSla, vo);
        vo.setStatus(workSla.getDisabled());
        vo.setRemindMode(Arrays.asList(workSla.getRemindMode().split(",")));
        vo.setModuleIds(workSlaModuleService.getModuleIdByWorkSlaId(id));
        vo.setSlaConditionVos(workSlaConditionService.getSlaConditionVosByWorkSlaId(id));
        return vo;
    }

    // 根据工单策略SLA ID获取详情
    @Override
    public WorkSlaDetailVo getDetail(Long id) {
        ZjWorkSla workSla = this.getById(id);
        Assert.notNull(workSla, "工单策略SLA参数[ "+ id +" ]的数据不存在");
        WorkSlaDetailVo vo = new WorkSlaDetailVo();
        BeanUtil.copyProperties(workSla, vo);
        vo.setStatus(workSla.getDisabled());
        vo.setRemindMode(Arrays.asList(workSla.getRemindMode().split(",")));
        vo.setModules(workSlaModuleService.getByWorkSlaIds(new ArrayList<>(Arrays.asList(id))).stream().map(WorkSlaModuleExtend::getModule).distinct().toList());
        List<WorkSlaConditionRemindEmpExtend> empExtendList = workSlaConditionRemindEmpService.getEmpByWorkSlaId(id);
        vo.setConditionVos(workSlaConditionService.getSlaConditionVosByWorkSlaId(id).stream().filter(WorkSlaConditionVo::getEnabled).map(cond -> {
            WorkSlaDetailConditionVo conditionVo = new WorkSlaDetailConditionVo();
            BeanUtil.copyProperties(cond, conditionVo);
            if (cond.getEnableBeforeOverTimeRemind() && cond.getBeforeOverTimeRemindEmpType().stream().anyMatch(f -> Objects.equals("2", f))) {
                conditionVo.setSlaBeforeOverTimeRemindEmps(empExtendList.stream().filter(f -> f.getType() == 1 && Objects.equals(f.getWorkSlaConditionId(), cond.getId())).map(WorkSlaConditionRemindEmpExtend::getEmp).toList());
            }
            if (cond.getEnableAfterOverTimeRemind() && cond.getAfterOverTimeRemindEmpType().stream().anyMatch(f -> Objects.equals("2", f))) {
                conditionVo.setSlaAfterOverTimeRemindEmps(empExtendList.stream().filter(f -> f.getType() == 1 && Objects.equals(f.getWorkSlaConditionId(), cond.getId())).map(WorkSlaConditionRemindEmpExtend::getEmp).toList());
            }
            return conditionVo;
        }).toList());
        return vo;
    }

    // 批量启用或禁用工单策略SLA
    @Override
    public void updateDisabledBatchById(List<Long> ids, boolean status) {
        if (CollectionUtil.isEmpty(ids)) {
            return;
        }
        workSlaMapper.updateDisabledBatchById(ids, status);
    }

    // 批量删除工单策略SLA
    @Override
    @Transactional
    public void deleteBatchByIds(List<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return;
        }
        workSlaConditionService.deleteByWorkSlaIds(ids);
        workSlaModuleService.deleteByWorkSlaIds(ids);
        workSlaConditionRemindEmpService.deleteByWorkSlaIds(ids);
        this.removeByIds(ids);
    }

    // 根据工单模块ID获取工单策略SLA
    @Override
    public List<WorkSlaExtend> getWorkSlaByModuleIds(List<Long> moduleIds, boolean selectSlaEmp) {
        if (CollectionUtil.isEmpty(moduleIds)) {
            return new ArrayList<>();
        }
        List<ZjWorkSlaModule> slaModuleList = workSlaModuleService.getByModuleIds(moduleIds);
        if (CollectionUtil.isEmpty(slaModuleList)) {
            return new ArrayList<>();
        }
        List<Long> workSlaIds = slaModuleList.stream().map(ZjWorkSlaModule::getWorkSlaId).distinct().toList();
        QueryWrapper<ZjWorkSla> wrapper = new QueryWrapper<>();
        wrapper.select("id", "date_type", "start_time", "end_time", "remind_mode")
                .eq("is_disabled", false)
                .in("id", workSlaIds);
        List<ZjWorkSla> workSlas = this.list(wrapper);
        List<ZjWorkSlaCondition> slaConditionList = workSlaConditionService.getByWorkSlaIds(workSlaIds);

        List<WorkSlaConditionRemindEmpExtend> conditionRemindEmpList = new ArrayList<>();
        if (selectSlaEmp) {
            conditionRemindEmpList.addAll(workSlaConditionRemindEmpService.getByWorkSlaIds(workSlaIds).stream().map(t -> {
                WorkSlaConditionRemindEmpExtend extend = new WorkSlaConditionRemindEmpExtend();
                BeanUtil.copyProperties(t, extend);
                return extend;
            }).toList());
        }
        return workSlas.stream().map(sla -> {
            WorkSlaExtend slaExtend = new WorkSlaExtend();
            BeanUtil.copyProperties(sla, slaExtend);
            slaExtend.setModuleIds(slaModuleList.stream().filter(f -> Objects.equals(f.getWorkSlaId(), sla.getId())).map(ZjWorkSlaModule::getModuleId).toList());
            slaExtend.setWorkSlaConditionExtends(slaConditionList.stream().filter(f -> Objects.equals(f.getWorkSlaId(), sla.getId())).map(cond -> {
                WorkSlaConditionExtend conditionExtend = new WorkSlaConditionExtend();
                BeanUtil.copyProperties(cond, conditionExtend);
                if (selectSlaEmp) {
                    conditionExtend.setWorkSlaConditionRemindEmpList(conditionRemindEmpList.stream().filter(f -> Objects.equals(f.getWorkSlaConditionId(), cond.getId())).toList());
                }
                return conditionExtend;
            }).toList());
            return slaExtend;
        }).toList();
    }

    // 获取工单SLA下拉数据
    @Override
    public Map<String, Object> getWorkSlaSelect(Long custAccId, SelectVo selectVo) {
        PageUtil.setSelectPageLimit(selectVo);
        QueryWrapper<ZjWorkSla> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name")
                .eq("cust_acc_id", custAccId)
                .eq("is_disabled", false);
        if (StringUtils.isNotBlank(selectVo.getName())) {
            wrapper.like("name", selectVo.getName());
        }
        Page<ZjWorkSla> page = this.page(new Page<>(selectVo.getPage(), selectVo.getLimit()), wrapper);
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), page.getTotal(), page.getRecords().stream().map(sla -> {
            return new SelectResultVo(sla.getId(), sla.getName());
        }).toList());
    }
}
